package the.workshop.bu.controller;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.wisteria.framework.util.TreeSelected;
import org.wisteria.framework.web.APIResult;
import org.wisteria.framework.web.QueryResult;
import the.broccoli.auth.UserContext;
import the.workshop.bu.controller.req.*;
import the.workshop.bu.controller.resp.ProductGetResp;
import the.workshop.bu.controller.resp.ProductMatchResp;
import the.workshop.bu.controller.resp.ProductSearchResp;
import the.workshop.bu.dto.ProductCondition;
import the.workshop.bu.dto.req.ProductQueryReq;
import the.workshop.bu.entity.Product;
import the.workshop.bu.service.IProductService;
import the.workshop.bu.service.dto.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 产品控制器
 *
 * @author lei.liu
 * @since 2020-06-24 15:38:05
 */
@RestController
@RequestMapping("/bu/product")
public class ProductController {

    @Resource
    private IProductService productService;

    @PostMapping("/add")
    public APIResult add(@ModelAttribute ProductAddReq req) {
        ProductSaveDTO dto = new ProductSaveDTO();
        BeanUtils.copyProperties(req, dto);
        dto.setOperatorId(UserContext.userId());
        dto.setOperatorName(UserContext.userName());
        dto.setAreaList(CollectionUtils.isEmpty(req.getAreaList()) ? null : req.getAreaList().stream().map(this::convertOfArea).collect(Collectors.toList()));
        productService.save(dto);
        return APIResult.success();
    }

    @PostMapping("/remove")
    public APIResult remove(@RequestParam(value = "ids", required = true) List<Integer> ids) {
        productService.removeByIds(ids, UserContext.userId(), UserContext.userName());
        return APIResult.success();
    }

    @PostMapping("/modify")
    public APIResult modify(@ModelAttribute ProductModifyReq req) {
        ProductModifyDTO dto = new ProductModifyDTO();
        BeanUtils.copyProperties(req, dto);
        dto.setOperatorId(UserContext.userId());
        dto.setOperatorName(UserContext.userName());
        dto.setAreaList(!StringUtils.hasText(req.getAreaList()) ? null : JSON.parseArray(req.getAreaList(), ProductModifyDTO.Area.class));
        productService.updateById(dto);
        return APIResult.success();
    }

    @PostMapping("/rule/modify")
    public APIResult<Boolean> modifyProductRule(@ModelAttribute ProductRuleModifyReq req) {
        ProductRuleModifyDTO dto = new ProductRuleModifyDTO();
        dto.setProductId(req.getProductId());
        dto.setRuleIdList(req.getRuleIdList());
        dto.setOperatorId(UserContext.userId());
        dto.setOperatorName(UserContext.userName());
        return APIResult.success(productService.updateProductRule(dto));
    }

    @GetMapping("/{id}")
    public APIResult<ProductGetResp> get(@PathVariable(value = "id") Integer id) {
        ProductGetDTO detail = productService.getDetailById(id);
        ProductGetResp resp = new ProductGetResp();
        BeanUtils.copyProperties(detail, resp);
        if (!CollectionUtils.isEmpty(detail.getAreaList())) {
            resp.setAreaList(detail.getAreaList().stream().map(this::convertOf).collect(Collectors.toList()));
        }
        return APIResult.success(resp);
    }

    @GetMapping("/page")
    public APIResult<QueryResult> page(@ModelAttribute ProductQueryReq req) {
        return APIResult.success(productService.pageList(req.toCondition(), req.getPageNum(), req.getPageSize()));
    }

    @GetMapping("/list")
    public APIResult<List<Product>> list() {
        return APIResult.success(productService.listByCondition(new ProductCondition()));
    }

    @PostMapping("/search")
    public APIResult<List<ProductSearchResp>> search(@RequestBody ProductSearchReq req) {
        ProductSearchConditionDTO dto = new ProductSearchConditionDTO();
        dto.setCityId(req.getCityId());
        dto.setProvinceId(req.getProvinceId());
        dto.setRuleIdList(req.getRuleIdList());
        List<ProductSearchResultDTO> productList = productService.search(dto);
        return APIResult.success(CollectionUtils.isEmpty(productList) ? null : productList.stream().map(this::convertOf).collect(Collectors.toList()));
    }

    @GetMapping("/rule/tree-selected/{productId}")
    public APIResult<TreeSelected> getProductRuleTreeSelected(@PathVariable(value = "productId") Integer productId) {
        return APIResult.success(productService.getProductRuleTreeSelected(productId));
    }

    @GetMapping("/area/tree-selected/{productId}")
    public APIResult<TreeSelected> getProductAreaTreeSelected(@PathVariable(value = "productId") Integer productId) {
        return APIResult.success(productService.getProductAreaTreeSelected(productId));
    }

    @PostMapping("/match")
    public APIResult<List<ProductMatchResp>> matchProduct(@RequestBody ProductMatchReq req) {
        ProductMatchDTO dto = new ProductMatchDTO();
        BeanUtils.copyProperties(req, dto);
        List<ProductMatchResultDTO> list = productService.matchProduct(dto);
        return APIResult.success(CollectionUtils.isEmpty(list) ? null : list.stream().map(this::covertOf).collect(Collectors.toList()));
    }

    private ProductSearchResp convertOf(ProductSearchResultDTO source) {
        ProductSearchResp target = new ProductSearchResp();
        target.setProductId(source.getProductId());
        target.setProductName(source.getProductName());
        target.setProductLogo(source.getProductLogo());
        target.setInterestYear(source.getInterestYear());
        target.setQuota(source.getQuota());
        target.setLegalPersonAgeStart(source.getLegalPersonAgeStart());
        target.setLegalPersonAgeEnd(source.getLegalPersonAgeEnd());
        return target;
    }

    private ProductSaveDTO.Area convertOfArea(ProductAddReq.Area source) {
        ProductSaveDTO.Area target = new ProductSaveDTO.Area();
        target.setProvinceId(source.getProvinceId());
        target.setCityId(source.getCityId());
        return target;
    }

    private ProductModifyDTO.Area convertOfArea(ProductModifyReq.Area source) {
        ProductModifyDTO.Area target = new ProductModifyDTO.Area();
        target.setProvinceId(source.getProvinceId());
        target.setCityId(source.getCityId());
        return target;
    }

    private ProductGetResp.Area convertOf(ProductGetDTO.Area source) {
        ProductGetResp.Area target = new ProductGetResp.Area();
        target.setProvinceId(source.getProvinceId());
        target.setCityId(source.getCityId());
        return target;
    }

    private ProductMatchResp covertOf(ProductMatchResultDTO source) {
        ProductMatchResp target = new ProductMatchResp();
        BeanUtils.copyProperties(source, target);
        return target;
    }

}